package com.kitty.game.talk.service;

import com.kitty.common.utils.SpringUtils;
import com.kitty.game.config.NPC;
import com.kitty.game.config.TalkSet;
import com.kitty.game.map.service.MapService;
import com.kitty.game.npc.message.ReqTaskTalk;
import com.kitty.game.npc.message.RespTaskTalk;
import com.kitty.game.pet.model.Pet;
import com.kitty.game.role.model.Role;
import com.kitty.game.school.SchoolDataPool;
import com.kitty.game.school.service.SchoolService;
import com.kitty.game.talk.TalkDataPool;
import com.kitty.game.talk.model.RoleTalk;
import com.kitty.game.task.service.NewTaskService;
import com.kitty.game.team.service.TeamService;
import com.kitty.game.utils.Const;
import com.kitty.listener.EventDispatcher;
import com.kitty.listener.EventType;
import com.kitty.listener.event.TalkEndEvent;
import com.kitty.mina.message.MessagePusher;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.json.Json;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
//后加
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class TalkService {
    Logger logger = LoggerFactory.getLogger(getClass());


    public TalkSet getTalkSet(int id, Role role) {
        return getTalkSet(id, (byte)role.getPolar(), role.getGender());
    }

    /***
     * 获得id对应的对话产品数据
     * @param id 对话ID
     * @param school 门派
     * @param sex 性别
     * @return
     */
    public TalkSet getTalkSet(int id, byte school, byte sex) {
        Map<Byte, Map<Byte, TalkSet>> talkMap = TalkDataPool.talkMapBySchoolSex.get(id);
        if (talkMap != null) {
            Map<Byte, TalkSet> talkBySchool = talkMap.get(school);
            if (talkBySchool != null) {
                return talkBySchool.get(sex);
            }
        }

        return null;
    }

    /**
     * 加载对话产品数据
     */
    public void loadTalkSet() {
        Dao dao = SpringUtils.getBean(Dao.class);
        List<TalkSet> list = dao.query(TalkSet.class, Cnd.NEW().orderBy("id", "ASC"));

        Map<Integer, Map<Byte, Map<Byte, TalkSet>>> talkMapBySchoolSex = newTalkMapBySchoolSex(list);
        Map<Integer, Integer> talkEndMap = newTalkEndMap(list);
        TalkDataPool.talkMapBySchoolSex = talkMapBySchoolSex;
        TalkDataPool.talkEndMap = talkEndMap;
    }

    private Map<Integer, Map<Byte, Map<Byte, TalkSet>>> newTalkMapBySchoolSex(List<TalkSet> list) {
        SchoolService schoolService = SpringUtils.getBean(SchoolService.class);
        /**需要先初始化门派数据*/
        if (SchoolDataPool.schoolMap == null) {
            schoolService.loadSchoolSet();
        }

        Map<Integer, Map<Byte, Map<Byte, TalkSet>>> talkMapBySchoolSet = new HashMap<>();
        Set<Byte> schoolSet = SchoolDataPool.schoolMap.keySet();
        List<Byte> sexSet = Arrays.asList(Const.SEX_FEMALE, Const.SEX_MALE);

        Map<Byte, Map<Byte, TalkSet>> mapBySchool = null;
        TalkSet tempTalkSet = null;

        for (TalkSet talkSet : list) {
            mapBySchool = new HashMap<>();
            talkMapBySchoolSet.put(talkSet.getId(), mapBySchool);

            tempTalkSet = talkSet;

            /**处理门派相关的，对话内容，NPC名字，NPC ICON*/
            for (Byte school : schoolSet) {
                /**对话内容 */
                String tempMsg = schoolService.replaceSchoolDesc(school, talkSet.getMsg());
                /**NPC名字*/
                String tempNpcName = schoolService.replaceSchoolDesc(school, talkSet.getNpcName());


                if (!tempMsg.equals(talkSet.getMsg()) || !tempNpcName.equals(talkSet.getNpcName())) {
                    try {
                        tempTalkSet = talkSet.clone();
                        tempTalkSet.setMsg(tempMsg);
                        tempTalkSet.setNpcName(tempNpcName);

                        /**根据NPC名字拿到NPC ICON*/
                        NPC npcSet = schoolService.getNpc(tempNpcName);
                        if (npcSet != null) {
                            tempTalkSet.setNpcIcon((short) npcSet.getIcon());
                        }
                        npcSet = SpringUtils.getBean(MapService.class).getNpcByName(tempNpcName);
                        if (npcSet != null) {
                            tempTalkSet.setNpcIcon((short) npcSet.getIcon());
                        }

                    } catch (CloneNotSupportedException e) {
                        new RuntimeException("clone对话配置时出现异常"+e.getMessage(), e);
                    }
                }

                Map<Byte, TalkSet> mapBySex = new HashMap<>();
                mapBySchool.put(school, mapBySex);

                /**处理性别相关的*/
                for (byte sex : sexSet) {
                    String tempMsgBySex = replaceSexDesc(sex, tempMsg);
                    if (!tempMsgBySex.equals(tempMsg)) {
                        try {
                            tempTalkSet = tempTalkSet.clone();
                            tempTalkSet.setMsg(tempMsgBySex);
                        } catch (CloneNotSupportedException e) {
                            new RuntimeException("clone对话配置时出现异常"+e.getMessage(), e);
                        }
                    }

                    mapBySex.put(sex, tempTalkSet);
                }
            }
        }

        return talkMapBySchoolSet;
    }

    /**替换性别相关的描述*/
    public String replaceSexDesc(byte sex, String desc) {
        String temp = desc;
        if (sex == Const.SEX_MALE) {
            temp = temp.replace("{yatou_or_xiaozi}", "小子");
            temp = temp.replace("{{xiaoyatou_or_xiaohuozi}}", "小伙子");
            temp = temp.replace("{gege_or_jiejie}", "哥哥");
            temp = temp.replace("{guniang_or_gongzi}", "公子");
        } else if (sex == Const.SEX_FEMALE) {
            temp = temp.replace("{yatou_or_xiaozi}", "丫头");
            temp = temp.replace("{xiaoyatou_or_xiaohuozi}", "小丫头");
            temp = temp.replace("{gege_or_jiejie}", "姐姐");
            temp = temp.replace("{guniang_or_gongzi}", "姑娘");
        }

        return temp;
    }

    private Map<Integer, Integer> newTalkEndMap(List<TalkSet> list) {
        Map<Integer, Integer> talkEndMap = new HashMap<>();
        Map<Integer, TalkSet>talkMap = new HashMap<>(list.size());
        for (TalkSet talkSet : list) {
            talkMap.put(talkSet.getId(), talkSet);
        }

        for (TalkSet talkSet : list) {
            TalkSet tempTalkSet = talkSet;
            for (int i=0, size = list.size(); i < size; i++) {
                TalkSet nextTalkSet = talkMap.get(tempTalkSet.getNextId());

                if (isEndTalk(tempTalkSet, nextTalkSet)) {
                    /**找到这段对话的结束对话*/
                    talkEndMap.put(talkSet.getId(), tempTalkSet.getId());
                    break;
                }

                /**没有找到则继续找*/
                tempTalkSet = nextTalkSet;
            }
        }

        return talkEndMap;
    }

    private boolean isEndTalk(TalkSet taslkSet, TalkSet nextTalkSet) {
        /**对话空白时，或者下一对话没有时，表示是这段对话的最后一个对话*/
        if (Strings.isEmpty(taslkSet.getMsg()) || nextTalkSet == null) {
            return true;
        }
        return false;
    }

    /**从传入map中获得对应数据*/
    public void loadCommonSet(Map<String ,String> commonSetMap) {
        String value = commonSetMap.get("study_skill_special_talk");
        if (value != null) {
            NutMap nutMap = Json.fromJson(NutMap.class, value);
            Map<Integer, Map<Byte, String>> skillSpecialTalk = new HashMap<>();
            int talkId = nutMap.getInt("talkId");
            Map<Byte, String> talkContent = new HashMap<>();
            NutMap talkContentNutMap = nutMap.getAs("talkContent", NutMap.class);
            List<Byte> list = Arrays.asList(Const.ATTRIB_TYPE_PHYCIAL, Const.ATTRIB_TYPE_MAGIC, Const.ATTRIB_TYPE_SELF);
            for (byte attribType : list) {
                String string = talkContentNutMap.getString(String.valueOf(attribType));
                talkContent.put(attribType, string);
            }
            skillSpecialTalk.put(talkId, talkContent);

            TalkDataPool.skillSpecialTalk = skillSpecialTalk;
        }
    }

    /**
     * 弹出第1个对话
     * 只能用在连续对话中的第1个对话，第1个对话之后要用popNextTalk方法
     *
     * @param role
     * @param talkSet
     */
    public void popFirstTalk(Role role, TalkSet talkSet) {
        //2022-06-03 修改为 只给队长弹
        /**未组队中*/
        popSingleFirstTalk(role, talkSet);
        TeamService teamService = SpringUtils.getTeamService();
        if (teamService.isInTeam(role)) {
            /**组队中*/
            if (teamService.isTeamLeader(role)) {
                popSingleFirstTalk(role, talkSet);
            }
        } else {
            /**未组队中*/
            popSingleFirstTalk(role, talkSet);
        }
    }

    private void popSingleFirstTalk(Role role, TalkSet talkSet) {
        if (SpringUtils.getFightService().isInFight(role)) {
            return ;
        }

        popTalk(role, talkSet);

        /**记录开始对话*/
        RoleTalk roleTalk = role.getTalk();
        roleTalk.startTalk(talkSet.getId());
    }

    public void popNextTalk(Role role) {
        TeamService teamService = SpringUtils.getTeamService();
        if (teamService.isInTeam(role)) {
            /**组队中*/
            if (teamService.isTeamLeader(role)) {
                popSingleNextTalk(role);
            }
        } else {
            /**未组队中*/
            popSingleNextTalk(role);
        }
    }

    /**
     * 弹出后续对话(前面已经有弹出对话)
     *
     * @param role
     */
    public void popSingleNextTalk(Role role) {
        /**先获得在对话的id，然后再弹出下一个对话*/
        RoleTalk roleTalk = role.getTalk();
        TalkSet talkSet = getTalkSet(roleTalk.getTalkId(), role);

        /**当前对话数据找不到时，则返回*/
        // TODO 是否需要 加上异常日志？
        if (talkSet == null) {
            logger.warn("弹出后续对话 roleId: {}, 当前对话不存在: {}", role.getRoleId(), roleTalk.getTalkId());
            return;
        }

        TalkSet nextTalk = getTalkSet(talkSet.getNextId(), role);
        /**找不到下一对话时，正常情况是对话的最后一个对话*/
        if (nextTalk == null) {
            /**找不到下一个对话时，返回空的对话*/
            return;
        }

        popTalk(role, nextTalk);


        /**记录弹出的这个后续对话*/
        roleTalk.continueTalk(nextTalk.getId());
    }

    /**
     * 结束对话
     *
     * @param role
     */
    public void endTalk(Role role) {
        /**先获得在对话的id*/
        RoleTalk roleTalk = role.getTalk();
        TalkSet talkSet = getTalkSet(roleTalk.getTalkId(), role);

        /**记录已经结束*/
        roleTalk.endTalk();
        /**产生一个对话结束事件*/
        if (talkSet != null) {
            /**有该对话数据时才产生事件*/
            EventDispatcher.getInstance().fireEvent(new TalkEndEvent(EventType.TALK_END, role, talkSet.getId()));
        }
    }

    /**
     * 跳过对话
     */
    private void jumpTalk(Role role) {
        // TODO 后面再想想跳过的时候需要做什么
        RoleTalk roleTalk = role.getTalk();
        TalkSet endTalkSet = getEndTalkSet(role, roleTalk.getTalkId());
        if (endTalkSet != null) {
            roleTalk.continueTalk(endTalkSet.getId());
        }
    }

    /**获得对应的结束对话*/
    private TalkSet getEndTalkSet(Role role, int talkId) {
        Integer endTalkId = TalkDataPool.talkEndMap.get(talkId);
        if (endTalkId != null) {
            return getTalkSet(endTalkId, role);
        }
        return null;
    }


    /**
     * 给role弹出对话产品数据的对话内容
     *
     * @param role
     * @param talkSet
     */
    private void popTalk(Role role, TalkSet talkSet) {
        RespTaskTalk respTaskTalk = new RespTaskTalk();
        if (talkSet.getNpcName().equals("玩家角色名")) {
            respTaskTalk.setMsg(talkSet.getMsg().replace("角色名字", role.getName()));
            respTaskTalk.setTalkId(role.getRoleId());
            respTaskTalk.setNpcName(role.getName());
            respTaskTalk.setNpcIcon(role.getRoleIcon());
        } else {
            respTaskTalk.setMsg(talkSet.getMsg().replace("角色名字", role.getName()));
            respTaskTalk.setTalkId(-1);
            respTaskTalk.setNpcName(talkSet.getNpcName());
            respTaskTalk.setNpcIcon(talkSet.getNpcIcon());
        }

        /**对话空白时，或者下一对话没有时，表示结束对话*/
        if (isEndTalk(talkSet, getTalkSet(talkSet.getNextId(), role))) {
            respTaskTalk.setPic_no((short) 0);
            respTaskTalk.setIsComplete((short) 1);
        } else {
            respTaskTalk.setPic_no((short) 1);
            respTaskTalk.setIsComplete((short) 0);
        }

        /**宠物飞升名字替换*/

        if (role.getExtendBox() != null && role.getExtendBox().getParams().get("flying_pet_id") != null) {
            Pet pet = SpringUtils.getPetService().getPetById((Integer) role.getExtendBox().getParams().get("flying_pet_id"), role);
            if(pet!=null){/**假如接了飞升任务但是宠物不存在了 会报空*/
                respTaskTalk.setMsg(respTaskTalk.getMsg().replace("{flying_pet_name}", pet.getName()));
            }
        }

        String specialTalkMsg = getSpecialTalkMsg(role, talkSet);
        if (specialTalkMsg != null) {
            respTaskTalk.setMsg(specialTalkMsg);
        }

        respTaskTalk.setTaskName(talkSet.getTaskName());
        MessagePusher.pushMessage(role, respTaskTalk);
    }

    /**获得特殊的对话内容*/
    private String getSpecialTalkMsg(Role role, TalkSet talkSet) {
        Map<Byte, String> map = TalkDataPool.skillSpecialTalk.get(talkSet.getId());
        if (map != null) {
            Map<String, Byte> autoAttrib = role.getExtendBox().getAutoAttrib();
                String msg = map.get((byte) role.getExtendBox().getAutoAttrib().get("type"));
                NewTaskService taskService = SpringUtils.getBean(NewTaskService.class);
                return msg.replace("{skillName}", taskService.getLearnSkillName(autoAttrib.get("type"), role.getPolar()));
        }

        return null;
    }

    /**
     * 处理任务对话请求
     */
    public void requestTaskTalk(Role role, int id, short type) {
        /**加上id等于0返回的判断是为了解决主线第1个任务的对话不能关闭问题*/
        if (id == 0) {return ;}

        /**分支判断处理*/
        switch (type) {
            case ReqTaskTalk.NEXT_TALK:
                popNextTalk(role);
                break;
            case ReqTaskTalk.END_TALK:
                endTalk(role);
                break;
            case ReqTaskTalk.JUMP_TALK:
                jumpTalk(role);
                break;
            default:

        }
    }

    /**登录处理*/
    public void handleLogin(Role role) {
        if (role == null) {return ;}

//        /**登录的时候结束对话*/
//        role.getTalk().endTalk();
    }
}
